/**
 * PlatformAccessInterceptor.java
 * 
 * Copyright@2015 OVT Inc. All rights reserved. 
 * 
 * May 4, 2015
 */
package com.ovt.doorbell.payment.api.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import com.ovt.doorbell.payment.api.exception.NoAccessException;
import com.ovt.doorbell.payment.common.model.JsonDocument;
import com.ovt.doorbell.payment.common.utils.CookieUtil;
import com.ovt.doorbell.payment.common.utils.StringUtils;
import com.ovt.doorbell.payment.dao.constant.ActiveState;
import com.ovt.doorbell.payment.dao.vo.User;
import com.ovt.doorbell.payment.service.UserService;
import com.ovt.doorbell.payment.service.context.SessionContext;
import com.ovt.doorbell.payment.service.exception.ServiceErrorCode;
import com.ovt.doorbell.payment.service.exception.ServiceException;

/**
 * PlatformAccessInterceptor do the following things: <li>identify user by
 * access token from cookies before call controller</li>
 * 
 * @Author zhi.liu
 * @Version 1.0
 * @See
 * @Since [OVT Cloud Platform]/[API] 1.0
 */
public class PlatformAccessInterceptor extends HandlerInterceptorAdapter
{
    @Autowired
    private UserService userService;

    @Override
    public boolean preHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler) throws Exception
    {
        super.preHandle(request, response, handler);

        // get from cookie
        String accessToken = CookieUtil.getCookie(request,
                CookieUtil.KEY_ACCESS_TOKEN);
        
        // get from parameter if can't find in cookies
        if (StringUtils.isBlank(accessToken))
        {
            accessToken = request.getParameter(CookieUtil.KEY_ACCESS_TOKEN);
        }

        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();

        if (StringUtils.isBlank(accessToken))
        {
            JsonDocument respBody = new JsonDocument(
                    ServiceErrorCode.NOT_LOGIN, "Requires authentication!");

            // Spring internal json converter
            converter.write(respBody, MediaType.APPLICATION_JSON,
                    new ServletServerHttpResponse(response));

            return false;
        }
        
        // initial user session
        initSessionContext(accessToken);

        // access forbidden case:
        JsonDocument respBody = null;
        if (SessionContext.getCurrentUser() == null)
        {
            respBody = new JsonDocument(ServiceErrorCode.INVALID_ACCESS,
                    "Invalid access!");
        }

        if (respBody != null)
        {
            converter.write(respBody, MediaType.APPLICATION_JSON,
                    new ServletServerHttpResponse(response));

            return false;
        }

        return true;
    }

    /**
     * Initial session context.
     * 
     * @param request
     * @throws ServiceException
     * @throws NoAccessException
     */
    private void initSessionContext(String accessToken)
            throws ServiceException, NoAccessException
    {
        User user = userService.getUserByAccessToken(accessToken);
        SessionContext.setCurrentUser(user);
    }

    @Override
    public void postHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception
    {
        super.postHandle(request, response, handler, modelAndView);

        SessionContext.destroy();
    }

}
